﻿using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Electrical;
using Autodesk.Revit.DB.Mechanical;
using YArchitech.LIB;
using YArchitech.Revit;
using HYRevitCode.GeometryUtility;
using YJKRGeometry;

namespace HYOpeningDetail
{
	internal class LinearBasedComponent : Component
	{
		public void DimDuctFunction(ElementInfo elementInfo, List<ElementInfo> lstFloorAndBeamInfo, ViewPlan viewPlan, Dictionary<XYZ, DataWall> dicWallCurve, List<double> lstAllLevelValues, Dictionary<XYZ, List<Curve>> dicCombineGridCurve, XYZ ptIntersect, Element eleIntersect, Autodesk.Revit.DB.Document doc)
		{
			this.m_doc = doc;
			this.m_lstAllLevelValues = lstAllLevelValues;
			this.m_eleIntersect = eleIntersect;
			this.m_lstFloorAndBeamInfo = lstFloorAndBeamInfo;
			this.GetElementWidth();
			Transaction transaction = new Transaction(this.m_doc, "Dim");
			try
			{
				transaction.Start();
				if (OpeningViewDataSetForm.BRadSelGrid)
				{
					this.GetElementBoundatyGrid(elementInfo, ptIntersect, viewPlan, dicCombineGridCurve, true);
				}
				else
				{
					this.CreateLocationDimensionByWallCurve(elementInfo, ptIntersect, viewPlan, dicWallCurve, true);
				}
				this.CreateLeaderDimension(elementInfo, ptIntersect, viewPlan, dicWallCurve);
				transaction.Commit();
			}
			catch (Exception)
			{
				transaction.RollBack();
			}
		}

		private void CreateLeaderDimension(ElementInfo elementInfo, XYZ ptIntersect, ViewPlan viewPlan, Dictionary<XYZ, DataWall> dicWallCurve)
		{
			string strLevelText = null;
			string strFamText = null;
			this.CreateLocationDimensionByWallCurve(elementInfo, ptIntersect, viewPlan, dicWallCurve, false);
			this.GetDimText(elementInfo, ref strLevelText, ref strFamText, ptIntersect, viewPlan);
			XYZ ptDimPosionFir = new XYZ(ptIntersect.X + NumbericTools.mmToFeet(800.0), ptIntersect.Y - NumbericTools.mmToFeet(400.0), ptIntersect.Z);
			base.LeaderDimension(ptIntersect, ptDimPosionFir, strFamText, strLevelText, viewPlan);
		}

		private bool CreateLocationDimensionByWallCurve(ElementInfo dicElementInfo, XYZ ptIntersect, ViewPlan viewPlan, Dictionary<XYZ, DataWall> dicWallCurve, bool ifMove = false)
		{
			dicWallCurve = (from k in dicWallCurve
			orderby k.Key.DistanceTo(ptIntersect)
			select k).ToDictionary((KeyValuePair<XYZ, DataWall> k) => k.Key, (KeyValuePair<XYZ, DataWall> k) => k.Value);
			if (dicWallCurve.Count > 0)
			{
				DataWall value = dicWallCurve.ElementAt(0).Value;
				XYZ key = dicWallCurve.ElementAt(0).Key;
				Curve curvrFirst = value.curvrFirst;
				Curve curveSecond = value.curveSecond;
				double dFirstWallWidth = value.dFirstWallWidth;
				double dSecondWallWidth = value.dSecondWallWidth;
				YJKCurve hycurve = new YJKCurve(curvrFirst);
				new YJKCurve(curveSecond);
				Curve curve;
				double num;
				XYZ direction;
				if (hycurve.PointIsOnCurve(ptIntersect))
				{
					curve = value.curveSecond;
					Curve curvrFirst2 = value.curvrFirst;
					num = value.dSecondWallWidth;
					direction = (curve as Line).Direction;
				}
				else
				{
					curve = value.curvrFirst;
					Curve curveSecond2 = value.curveSecond;
					num = value.dFirstWallWidth;
					direction = (curve as Line).Direction;
				}
				XYZ project = new YJKCurve(curve.CreateOffset(num * 0.5, XYZ.BasisZ)).GetProject(ptIntersect, false);
				XYZ xyz = new XYZ(project.X, project.Y, ptIntersect.Z);
				Line dimNewLine = Line.CreateBound(xyz, ptIntersect);
				base.CreateDetailLine(xyz, ptIntersect, direction, viewPlan, dimNewLine, ifMove);
				return true;
			}
			return false;
		}

		private bool GetElementBoundatyGrid(ElementInfo elementInfo, XYZ ptIntersect, ViewPlan viewPlan, Dictionary<XYZ, List<Curve>> dicCombineGridCurve, bool ifMove = false)
		{
			dicCombineGridCurve = (from k in dicCombineGridCurve
			orderby k.Key.DistanceTo(ptIntersect)
			select k).ToDictionary((KeyValuePair<XYZ, List<Curve>> k) => k.Key, (KeyValuePair<XYZ, List<Curve>> k) => k.Value);
			if (dicCombineGridCurve.Count > 0)
			{
				XYZ key = dicCombineGridCurve.ElementAt(0).Key;
				List<Curve> value = dicCombineGridCurve.ElementAt(0).Value;
				Curve elemLocationCurve = PublicFunction.GetElemLocationCurve(elementInfo.element);
				List<Curve> curveProjectPoint = PublicFunction.GetCurveProjectPoint(value, ptIntersect);
				YJKLine hyline = new YJKLine(curveProjectPoint[0] as Line);
				new YJKLine(curveProjectPoint[1] as Line);
				Curve curve;
				XYZ vectorMove;
				if (hyline.IsParallel(elemLocationCurve as Line))
				{
					curve = curveProjectPoint[0];
					Curve curve2 = curveProjectPoint[1];
					vectorMove = (curve as Line).Direction.Normalize();
				}
				else
				{
					curve = curveProjectPoint[1];
					Curve curve3 = curveProjectPoint[0];
					vectorMove = (curve as Line).Direction.Normalize();
				}
				XYZ project = new YJKCurve(curve).GetProject(ptIntersect, false);
				Line dimNewLine = Line.CreateBound(ptIntersect, project);
				base.CreateDetailLine(project, ptIntersect, vectorMove, viewPlan, dimNewLine, ifMove);
				return true;
			}
			return false;
		}

		private void GetDimText(ElementInfo elementInfo, ref string strLevelText, ref string strFamText, XYZ dimPosion, ViewPlan viewPlan)
		{
			Element element = elementInfo.element;
			Curve elemLocationCurve = PublicFunction.GetElemLocationCurve(element);
			double value = 0.0;
			double num = 0.0;
			double num2 = 0.0;
			double value2 = 0.0;
			Parameter parameter = base.GetParameter(element, "长度");
			Parameter parameter2 = base.GetParameter(element, "宽度");
			Parameter parameter3 = base.GetParameter(element, "高度");
			Parameter parameter4 = base.GetParameter(element, "进深");
			Parameter parameter5 = element.get_Parameter(BuiltInParameter.INSTANCE_FREE_HOST_OFFSET_PARAM);
			Parameter parameter6 = element.get_Parameter(BuiltInParameter.SCHEDULE_LEVEL_PARAM);
			if (parameter != null)
			{
				value = NumbericTools.feetTomm(parameter.AsDouble());
			}
			if (parameter2 != null)
			{
				num = NumbericTools.feetTomm(parameter2.AsDouble());
			}
			if (parameter3 != null)
			{
				num2 = NumbericTools.feetTomm(parameter3.AsDouble());
			}
			if (parameter4 != null)
			{
				value2 = NumbericTools.feetTomm(parameter4.AsDouble());
			}
			if (parameter5 != null)
			{
				NumbericTools.feetTomm(parameter5.AsDouble());
			}
			if (parameter6 != null)
			{
				parameter6.AsDouble();
			}
			double elevation = viewPlan.GenLevel.Elevation;
			double num3 = this.GetDimBottomLevel(elemLocationCurve.GetEndPoint(0).Z, num2, elevation);
			Convert.ToInt32(value).ToString();
			Convert.ToInt32(value2).ToString();
			string str = Convert.ToInt32(num + 100.0).ToString();
			string str2 = Convert.ToInt32(num2 + 120.0).ToString();
			if (elementInfo.element is Duct)
			{
				this.CreateDetail(element, dimPosion, viewPlan, num);
				strFamText = string.Concat(new string[]
				{
					"留洞",
					Convert.ToInt32(num + 100.0).ToString(),
					"X",
					Convert.ToInt32(num2 + 100.0).ToString(),
					"(H)"
				});
				double feet = 0.0;
				if (PublicFunction.GetElementBaseZToNearLevel(elementInfo, out feet))
				{
					num3 = NumbericTools.feetTomm(feet);
				}
				strLevelText = "洞底标高: H+" + Convert.ToInt32(num3 - 50.0).ToString();
				return;
			}
			if (elementInfo.element is CableTray)
			{
				ElementId typeId = (elementInfo.element as CableTray).GetTypeId();
				string name = this.m_doc.GetElement(typeId).Name;
				strFamText = name + str + "X" + str2;
				if (OpeningViewDataSetForm.BChkBeamDimTop)
				{
					bool flag = false;
					Curve distanceFloorOrBeam = this.GetDistanceFloorOrBeam(this.m_lstFloorAndBeamInfo, elemLocationCurve, viewPlan, ref flag);
					if (distanceFloorOrBeam != null)
					{
						double dimTopLevel = this.GetDimTopLevel(elemLocationCurve, distanceFloorOrBeam, num2, elevation);
						if (flag)
						{
							strLevelText = "洞顶距梁底: H+" + Convert.ToInt32(dimTopLevel).ToString();
						}
						else
						{
							strLevelText = "洞顶距板底: H+" + Convert.ToInt32(dimTopLevel).ToString();
						}
					}
					else
					{
						strLevelText = "洞顶上方无梁和板";
					}
				}
				if (OpeningViewDataSetForm.BChkBeamDimBottom)
				{
					strLevelText = "洞底标高: H+" + Convert.ToInt32(num3 - 60.0).ToString();
				}
			}
		}

		private void CreateDetail(Element elem, XYZ dimPosion, ViewPlan viewPlan, double dWidth)
		{
			try
			{
				double num = 100.0;
				XYZ xyz = (PublicFunction.GetElemLocationCurve(elem) as Line).Direction.Normalize();
				XYZ xyz2 = xyz.CrossProduct(XYZ.BasisZ).Normalize();
				XYZ xyz3 = 0.5 * xyz2 * NumbericTools.mmToFeet(dWidth + num);
				XYZ xyz4 = 0.5 * xyz * this.m_dWallWidth;
				XYZ xyz5 = dimPosion.Add(xyz4).Add(xyz3);
				XYZ xyz6 = dimPosion.Add(xyz4).Subtract(xyz3);
				XYZ xyz7 = dimPosion.Subtract(xyz4).Subtract(xyz3);
				XYZ xyz8 = dimPosion.Subtract(xyz4).Add(xyz3);
				ElementSet elementSet = new ElementSet();
				Line line = Line.CreateBound(xyz5, xyz6);
				elementSet.Insert(this.m_doc.Create.NewDetailCurve(viewPlan, line));
				Line line2 = Line.CreateBound(xyz6, xyz7);
				elementSet.Insert(this.m_doc.Create.NewDetailCurve(viewPlan, line2));
				Line line3 = Line.CreateBound(xyz7, xyz8);
				elementSet.Insert(this.m_doc.Create.NewDetailCurve(viewPlan, line3));
				Line line4 = Line.CreateBound(xyz8, xyz5);
				elementSet.Insert(this.m_doc.Create.NewDetailCurve(viewPlan, line4));
				Line line5 = Line.CreateBound(xyz5, xyz7);
				elementSet.Insert(this.m_doc.Create.NewDetailCurve(viewPlan, line5));
				Line line6 = Line.CreateBound(xyz6, xyz8);
				elementSet.Insert(this.m_doc.Create.NewDetailCurve(viewPlan, line6));
				this.m_doc.CreatYJKGroup(elementSet);
			}
			catch (Exception)
			{
			}
		}

		private void GetElementWidth()
		{
			Wall wall = this.m_eleIntersect as Wall;
			if (wall != null)
			{
				this.m_dWallWidth = PublicFunction.GetWallWidth(wall);
				return;
			}
			FamilyInstance familyInstance = this.m_eleIntersect as FamilyInstance;
			if (base.GetParameter(familyInstance.Symbol, "b") != null)
			{
				this.m_dWallWidth = base.GetParameter(familyInstance.Symbol, "b").AsDouble();
			}
		}

		private double GetDimBottomLevel(double dOffset, double dHeight, double dLevelValue)
		{
			if (OpeningViewDataSetForm.BChkBeamDimBottom)
			{
				return NumbericTools.feetTomm(dOffset - dLevelValue) - 0.5 * dHeight;
			}
			return 0.0;
		}

		private double GetDimTopLevel(Curve locationCurve, Curve curveProjection, double dHeight, double dLevelValue)
		{
			if (OpeningViewDataSetForm.BChkBeamDimTop)
			{
				return NumbericTools.feetTomm(curveProjection.GetEndPoint(0).Z - locationCurve.GetEndPoint(0).Z) - 0.5 * dHeight;
			}
			return 0.0;
		}

		private Face GetBottomFace(Element element, Transform eleTransform)
		{
			List<Solid> allSolid = GeometryUtilityMethod.GetAllSolid(element.get_Geometry(new Options
			{
				ComputeReferences = true,
                DetailLevel = (ViewDetailLevel)3
			}), eleTransform);
			Face result = null;
			foreach (Solid solid in allSolid)
			{
				foreach (object obj in solid.Faces)
				{
					PlanarFace planarFace = obj as PlanarFace;
					if (planarFace != null && planarFace.FaceNormal().Z < 0.0)
					{
						result = planarFace;
						break;
					}
				}
			}
			return result;
		}

		private Curve GetDistanceFloorOrBeam(List<ElementInfo> lstFloorAndBeamInfo, Curve curveCableTray, ViewPlan viewPlan, ref bool bIsBeam)
		{
			if (lstFloorAndBeamInfo != null && lstFloorAndBeamInfo.Count < 1)
			{
				return null;
			}
			double val = this.FindNextLevel(viewPlan.GenLevel.Elevation);
			List<Face> list = new List<Face>();
			List<Face> list2 = new List<Face>();
			Curve result = null;
			bool flag = false;
			foreach (ElementInfo elementInfo in lstFloorAndBeamInfo)
			{
				if (elementInfo.element is FamilyInstance)
				{
					if (elementInfo.revitLink != null)
					{
						Level level = elementInfo.revitLink.Document.GetElement(elementInfo.element.GetParameter(BuiltInParameter.INSTANCE_REFERENCE_LEVEL_PARAM).AsElementId()) as Level;
						if (Geometry.IsEqual(val, level.Elevation))
						{
							list.Add(this.GetBottomFace(elementInfo.element, elementInfo.revitLink.GetTotalTransform()));
						}
					}
					else
					{
						Level level = this.m_doc.GetElement(elementInfo.element.GetParameter(BuiltInParameter.INSTANCE_REFERENCE_LEVEL_PARAM).AsElementId()) as Level;
						if (Geometry.IsEqual(val, level.Elevation))
						{
							list.Add(this.GetBottomFace(elementInfo.element, null));
						}
					}
				}
				else if (elementInfo.revitLink != null)
				{
					Level level2 = elementInfo.revitLink.Document.GetElement(elementInfo.element.GetParameter(BuiltInParameter.LEVEL_PARAM).AsElementId()) as Level;
					if (Geometry.IsEqual(val, level2.Elevation))
					{
						list2.Add(this.GetBottomFace(elementInfo.element, elementInfo.revitLink.GetTotalTransform()));
					}
				}
				else
				{
					Level level2 = this.m_doc.GetElement(elementInfo.element.GetParameter(BuiltInParameter.LEVEL_PARAM).AsElementId()) as Level;
					if (Geometry.IsEqual(val, level2.Elevation))
					{
						list2.Add(this.GetBottomFace(elementInfo.element, null));
					}
				}
			}
			foreach (Face face in list)
			{
				PlanarFace inputPlanarFace = face as PlanarFace;
				flag = this.CurveProjectToPlanarFace(curveCableTray, inputPlanarFace, out result);
				if (flag)
				{
					bIsBeam = true;
					break;
				}
			}
			if (!flag)
			{
				foreach (Face face2 in list2)
				{
					PlanarFace inputPlanarFace2 = face2 as PlanarFace;
					flag = this.CurveProjectToPlanarFace(curveCableTray, inputPlanarFace2, out result);
					if (flag)
					{
						bIsBeam = false;
						break;
					}
				}
			}
			return result;
		}

		private double FindNextLevel(double dLevelValue)
		{
			for (int i = 0; i < this.m_lstAllLevelValues.Count; i++)
			{
				if (Geometry.IsEqual(dLevelValue, this.m_lstAllLevelValues[i]) && i + 1 <= this.m_lstAllLevelValues.Count)
				{
					return this.m_lstAllLevelValues[i + 1];
				}
			}
			double num = 20.0;
			return this.m_lstAllLevelValues.Last<double>() + num;
		}

		public bool CurveProjectToPlanarFace(Curve inputCurve, PlanarFace inputPlanarFace, out Curve projectCurve)
		{
			projectCurve = null;
			if (null == inputCurve || null == inputPlanarFace || !inputCurve.IsBound)
			{
				return false;
			}
			List<XYZ> list = new List<XYZ>();
			List<XYZ> list2 = new List<XYZ>();
			double num = 0.0;
			while (Geometry.Lessthan_Or_Equal(num, 1.0))
			{
				list2.Add(inputCurve.Evaluate(num, true));
				num += 0.005;
			}
			bool flag = false;
			foreach (XYZ xyz in list2)
			{
				flag = false;
				IntersectionResult intersectionResult = null;
				intersectionResult = inputPlanarFace.Project(xyz);
				if (intersectionResult != null && intersectionResult.XYZPoint != null)
				{
					using (List<XYZ>.Enumerator enumerator2 = list.GetEnumerator())
					{
						while (enumerator2.MoveNext())
						{
							if (enumerator2.Current.IsAlmostEqualTo(intersectionResult.XYZPoint))
							{
								flag = true;
								break;
							}
						}
					}
					if (!flag)
					{
						list.Add(intersectionResult.XYZPoint);
					}
				}
			}
			if (list.Count < 2)
			{
				return false;
			}
			if (inputCurve is Arc && list.Count > 2)
			{
				try
				{
					projectCurve = Arc.Create(list[0], list[list.Count - 1], list[list.Count / 2]);
					goto IL_16A;
				}
				catch (Exception)
				{
					return false;
				}
			}
			try
			{
				projectCurve = Line.CreateBound(list[0], list[list.Count - 1]);
			}
			catch (Exception)
			{
				return false;
			}
			IL_16A:
			return null != projectCurve;
		}

		private double m_dWallWidth;

		private Element m_eleIntersect;

		private List<double> m_lstAllLevelValues;

		private List<ElementInfo> m_lstFloorAndBeamInfo;
	}
}
